package ru.andrew.jclazz.gui;

import java.awt.Toolkit;
import java.awt.datatransfer.*;
import java.io.*;
import java.util.Map;
import javax.swing.*;
import ru.andrew.jclazz.core.Clazz;
import ru.andrew.jclazz.decompiler.*;

public class DecompileForm extends JDialog implements ClipboardOwner
{
    private Clazz clazz;
    private String source;

    public DecompileForm()
    {
        initComponents();

        setContentPane(decompilePanel);
    }

    public void lostOwnership(Clipboard clipboard, Transferable contents)
    {
        // Do nothing
    }

    public void setClazz(Clazz clazz)
    {
        this.clazz = clazz;
        setTitle(clazz.getThisClassInfo().getFullyQualifiedName());

        decompile(null);
    }

    private void decompile(Map params)
    {
        try
        {
            ClazzSourceView csv = ClazzSourceViewFactory.getClazzSourceView(clazz);
            csv.setDecompileParameters(params);
            source = csv.getSource();

            String sourceText = source;

            sourceText = sourceText.replaceAll(" ", "&nbsp;");
            sourceText = sourceText.replaceAll("<", "&lt;");
            sourceText = sourceText.replaceAll(">", "&gt;");
            sourceText = sourceText.replaceAll("\n", "<BR>");
            sourcePane.setText(sourceText);
            sourcePane.setCaretPosition(0);
        }
        catch (Throwable ex)
        {
            sourcePane.setText("Exception occured while decompiling");

            String link = "http://sourceforge.net/tracker/?group_id=226227&atid=1066690";
            String exception = unpackException(ex);

            JTextPane text = new JTextPane();
            text.setContentType("text/html");
            text.setText("<html>Error occured while decompiling!<BR>Please submit bug at <b>" + link + "</b><BR>" + exception + "</html>");
            text.setEditable(false);
            text.setBackground(this.getBackground());

            JOptionPane.showMessageDialog(this, text, "Error", JOptionPane.ERROR_MESSAGE);

            throw new IllegalArgumentException("Error decompiling");
        }
    }

    private String unpackException(Throwable ex)
    {
        PrintWriter pw = null;
        try
        {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            pw = new PrintWriter(new OutputStreamWriter(baos));
            ex.printStackTrace(pw);
            pw.flush();
            String str = baos.toString();
            int ind = 0;
            int cnt = 0;
            while (ind != -1 && cnt < 5)
            {
                ind = str.indexOf("\n", ind + 1);
                cnt++;
            }
            if (ind != -1)
            {
                str = str.substring(0, ind);
            }
            str = str.replaceAll("\n", "<BR>");
            return str;
        }
        finally
        {
            pw.close();
        }
    }

    private void saveToFile()
    {
        JFileChooser chooser = new JFileChooser();
        String saveName = clazz.getFileName();
        saveName = saveName.substring(0, saveName.lastIndexOf('.')) + ".java";
        chooser.setSelectedFile(new File(saveName));

        int returnVal = chooser.showSaveDialog(this);
        if(returnVal != JFileChooser.APPROVE_OPTION)
        {
            JOptionPane.showMessageDialog(this, "No file specified", "Try again...", JOptionPane.WARNING_MESSAGE);
            return;
        }
        try
        {
            PrintWriter pw = new PrintWriter(new FileOutputStream(chooser.getSelectedFile()));
            pw.println(source);
            pw.close();
        }
        catch (IOException ioe)
        {
            JOptionPane.showMessageDialog(this, ioe.toString(), "Input/Output Exception", JOptionPane.ERROR_MESSAGE);
            System.exit(1);
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        decompilePanel = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        sourcePane = new javax.swing.JTextPane();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu2 = new javax.swing.JMenu();
        savaAsMenuItem = new javax.swing.JMenuItem();
        CtrlCMenuItem = new javax.swing.JMenuItem();

        setName("decompileFrame"); // NOI18N
        getContentPane().setLayout(new java.awt.GridBagLayout());

        decompilePanel.setLayout(new java.awt.GridBagLayout());

        sourcePane.setContentType("text/html");
        sourcePane.setEditable(false);
        sourcePane.setDisabledTextColor(new java.awt.Color(0, 0, 0));
        sourcePane.setEnabled(false);
        jScrollPane2.setViewportView(sourcePane);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        decompilePanel.add(jScrollPane2, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        getContentPane().add(decompilePanel, gridBagConstraints);

        jMenu2.setText("Edit");

        savaAsMenuItem.setText("Save as...");
        savaAsMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                savaAsMenuItemActionPerformed(evt);
            }
        });
        jMenu2.add(savaAsMenuItem);

        CtrlCMenuItem.setText("Copy All to Clipboard");
        CtrlCMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                CtrlCMenuItemActionPerformed(evt);
            }
        });
        jMenu2.add(CtrlCMenuItem);

        jMenuBar1.add(jMenu2);

        setJMenuBar(jMenuBar1);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void savaAsMenuItemActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_savaAsMenuItemActionPerformed
    {//GEN-HEADEREND:event_savaAsMenuItemActionPerformed
        saveToFile();
    }//GEN-LAST:event_savaAsMenuItemActionPerformed

    private void CtrlCMenuItemActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_CtrlCMenuItemActionPerformed
    {//GEN-HEADEREND:event_CtrlCMenuItemActionPerformed
        Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(source), this);
    }//GEN-LAST:event_CtrlCMenuItemActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem CtrlCMenuItem;
    private javax.swing.JPanel decompilePanel;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JMenuItem savaAsMenuItem;
    private javax.swing.JTextPane sourcePane;
    // End of variables declaration//GEN-END:variables

}
